package Game.Objects;

import java.lang.reflect.InvocationTargetException;

import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;

import Game.Level;
import GameMath.GPoint;

// TODO: durability

/** Game object base class
 * @author Aikidos
 */
public class GameObject {
	
	/** Is destroyed? */
	private boolean _isDestroyed = false;
	
	/** Object sprite */
	private Image _sprite;
	
	protected ObjectManager _objectManager;
	
	/** Object name */
	protected String _name;
	
	protected boolean _isCreature = false;
	protected boolean _isPlayer = false;
	
	/** Is can be used? */
	protected boolean _isCanBeUsed = false;
	
	/** Layer for drawing */
	protected int _layerForDrawing = 0;
	
	/** Type of object */
	public EGameObjectType Type = EGameObjectType.Neutral;
	
	public enum EGameObjectType {
		Neutral,
		Enemy,
		Ally
	}
	
	/** Position of object */
	public Vector2f Position = new Vector2f();
	
	public GameObject(ObjectManager objectManager, String name) {
		_objectManager = objectManager;
		_objectManager.addObject(this);
		_name = name;
	}
	
	/** Returns true if object is destroyed
	 * @return True if object is destroyed
	 */
	public boolean isDestroyed() {
		return _isDestroyed;
	}
	
	/** Returns true if object is player
	 * @return True if object is player
	 */
	public boolean isCreature() {
		return _isCreature;
	}
	
	/** Returns true if object is creature
	 * @return True if object is creature
	 */
	public boolean isPlayer() {
		return _isPlayer;
	}
	
	/** Returns true if object can be used
	 * @return True if object can be used
	 */
	public boolean isCanBeUsed() {
		return _isCanBeUsed;
	}
	
	/** Destroy object */
	public void destroy() {
		_isDestroyed = true;
	}
	
	/** Returns layer for drawing
	 * @return Layer for drawing
	 */
	public int getLayerForDrawing() {
		return _layerForDrawing;
	}
	
	/** Returns object name
	 * @return Object name
	 */
	public String getName() {
		return _name;
	}
	
	/** Returns object sprite
	 * @return Object sprite
	 */
	public Image getSprite() {
		return _sprite;
	}

	/** Convert position to map coordinate
	 * @return Map coordinate
	 */
	public GPoint getCoord() {
		GPoint ret = new GPoint((int) (Position.x - (Level.BLOCK_SIZE / 2)),
				(int) (Position.y - (Level.BLOCK_SIZE / 2)));
		ret.x /= Level.BLOCK_SIZE;
		ret.y /= Level.BLOCK_SIZE;
		
		return ret;
	}
	
	/** Returns object manager
	 * @return Object manager
	 */
	public ObjectManager getObjectManager() {
		return _objectManager;
	}
	
	/** Set object coordinates
	 * @param coord - Coordinates
	 */
	public void setCoord(GPoint coord) {
		Position = _objectManager.coordToObjectPos(coord);
	}
	
	/** Set sprite
	 * @param sprite - Sprite for object
	 * @throws SlickException 
	 */
	public void setSprite(Image sprite) throws SlickException {
		if (_sprite != null) {
			_sprite.destroy();
			_sprite = null;
		}
		
		_sprite = sprite;
	}
	
	/** Set layer for drawing 
	 * @param layer - Layer
	 */
	public void setLayerForDrawing(int layer) {
		_layerForDrawing = layer;
	}
	
	/** Update object
	 * @param delta - Time delta
	 */
	public void update(int delta) throws SlickException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
		
	}
	
	/** Draw object
	 * @param g - Slick2d graphics
	 */
	public void draw(Graphics g) {
		if (_sprite != null)
		{
			GPoint coord = getCoord();
			_sprite.setAlpha(_objectManager.getLevel().getLightManager().getLightMap().getMap()[coord.x][coord.y].getIllumination());
			
			Vector2f offset = _objectManager.getLevel().getObjectManager().getCamera().getDrawOffset();
			
			// Set sprite draw origin
			Vector2f origin = new Vector2f(_sprite.getWidth() / 2, _sprite.getHeight() / 2);
			
			g.drawImage(_sprite, (Position.x - origin.x) - offset.x, 
					(Position.y - origin.y) - offset.y);
		}
	}
	
	/** Step update 
	 * @throws SlickException */
	public void step() throws SlickException {
		
	}
	
	/** Use object
	 * @param user - User
	 */
	public void use(GameObject user) throws SlickException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
		
	}
	
	/** Call when was a collision with other object
	 * @param other - Other object
	 * @param moveOn - True if object move to other object coordinates,
	 * false if object stay, but other object move to him
	 * @return If movement is allowed that returns 'true'.
	 * @throws SlickException 
	 */
	public boolean onCollision(GameObject other, boolean moveOn) throws SlickException {
		return true;
	}
}
